Immutable 객체
Immutable 객체
개요
Immutable 객체(불변 객체)는 객체지향프로그래밍(OOP)에서 중요한 개념 중 하나로, 객체가 생성된 이후 그 내부 상태를 변경할 수 없는 객체를 의미합니다. 즉, Immutable 객체는 초기화된 후 어떤 메서드도 내부 데이터를 수정하지 않으며, 상태 변경이 필요한 경우 기존 객체를 수정하는 대신 새로운 객체를 생성하여 반환합니다. 이는 프로그램의 안정성, 스레드 안정성(thread safety), 디버깅 용이성, 그리고 함수형 프로그래밍과의 호환성 측면에서 큰 장점을 제공합니다.
Immutable 객체는 Java, Python, C#, Kotlin 등 다양한 객체지향 언어에서 활용되며, 특히 동시성 프로그래밍(concurrent programming)과 함수형 프로그래밍 패러다임에서 핵심적인 역할을 합니다.
Immutable 객체의 특징
Immutable 객체는 다음과 같은 주요 특징을 가집니다:
- 상태 변경 불가: 객체 생성 후 필드 값이 변경되지 않음.
- 스레드 안전성: 공유 데이터가 변경되지 않기 때문에 멀티스레드 환경에서 안전하게 사용 가능.
- 해시 기반 컬렉션에 적합: 해시 값이 변하지 않아
[HashMap](/doc/%EA%B8%B0%EC%88%A0/%EC%9E%90%EB%B0%94/%EC%BB%AC%EB%A0%89%EC%85%98%20%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC/HashMap),[HashSet](/doc/%EA%B8%B0%EC%88%A0/%EC%9E%90%EB%B0%94/%EC%BB%AC%EB%A0%89%EC%85%98%20%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC/HashSet)등에 안전하게 사용 가능. - 캐싱 및 재사용 용이: 동일한 상태의 객체는 캐싱하여 재사용할 수 있음.
- 예측 가능한 동작: 객체의 상태가 변하지 않기 때문에 디버깅과 테스트가 쉬움.
Immutable 객체의 예시
Java에서의 Immutable 객체
Java에서는 [String](/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/%EC%9E%90%EB%A3%8C%ED%98%95/String), [Integer](/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/%EC%9E%90%EB%A3%8C%ED%98%95/Integer), [LocalDateTime](/doc/%EA%B8%B0%EC%88%A0/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D/%EC%9E%90%EB%A3%8C%ED%98%95/LocalDateTime) 등이 대표적인 Immutable 클래스입니다.
String str = "Hello";
str = str.concat(" World"); // 새로운 String 객체를 생성
위 코드에서 concat() 메서드는 기존 str 객체를 수정하지 않고, "Hello World"를 담은 새로운 String 객체를 반환합니다. 이는 String 클래스가 내부적으로 final 필드를 사용하고, 모든 상태 변경 메서드가 새로운 인스턴스를 반환하도록 설계되어 있기 때문입니다.
사용자 정의 Immutable 클래스를 작성하는 예시:
public final class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
// 상태 변경이 필요한 경우 새로운 객체 생성
public Person withAge(int newAge) {
return new Person(this.name, newAge);
}
}
final class: 상속 불가능하게 하여 하위 클래스에서 상태를 변경하는 것을 방지.private final필드: 내부 상태 변경 불가.- 게터만 제공, 세터 미제공.
- 상태 변경이 필요한 경우
withAge()처럼 새로운 객체를 반환하는 메서드 제공 (Fluent API 스타일).
Immutable 객체의 장점
| 장점 | 설명 |
|---|---|
| 스레드 안전성 | 객체가 변경되지 않기 때문에 여러 스레드가 동시에 접근해도 데이터 경합(race condition) 발생하지 않음. |
| 예측 가능한 상태 | 객체의 상태가 생성 후 변하지 않아, 디버깅과 테스트가 용이함. |
| 캐싱 및 재사용 | 동일한 값을 가진 객체는 캐싱하여 메모리 사용을 최적화할 수 있음 (예: String Pool). |
| 함수형 프로그래밍과의 호환성 | 순수 함수(pure function)와 잘 어울림. 상태 부작용(side effect) 없음. |
| 컬렉션의 키로 사용 가능 | 해시 값이 변하지 않으므로 HashMap의 키로 안전하게 사용 가능. |
Immutable 객체의 단점
- 성능 오버헤드: 상태 변경 시마다 새로운 객체를 생성하므로, 빈번한 변경이 발생하면 메모리 사용량과 GC(Garbage Collection) 부담이 증가할 수 있음.
- 복잡한 객체 구조에서는 불편: 내부에 컬렉션을 포함하는 경우, 해당 컬렉션도 불변으로 관리해야 함.
- 일부 언어에서는 지원 부족: 모든 언어가 Immutable 객체를 쉽게 만들 수 있는 기능을 제공하지는 않음.
Immutable 객체와 Mutable 객체 비교
| 구분 | Immutable 객체 | Mutable 객체 |
|---|---|---|
| 상태 변경 | 불가능 | 가능 |
| 스레드 안전성 | 높음 | 낮음 (동기화 필요) |
| 메모리 사용 | 변경 시 새 객체 생성 → 더 큼 | 기존 객체 재사용 → 작음 |
| 사용 예시 | String, LocalDateTime |
[StringBuilder](/doc/%EA%B8%B0%EC%88%A0/%EC%9E%90%EB%B0%94/%EB%AC%B8%EC%9E%90%EC%97%B4%20%EC%B2%98%EB%A6%AC/StringBuilder), [ArrayList](/doc/%EA%B8%B0%EC%88%A0/%EC%9E%90%EB%B0%94/%EC%BB%AC%EB%A0%89%EC%85%98%20%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC/ArrayList) |
언어별 Immutable 객체 지원
- Java:
final키워드, 불변 클래스 설계,[Collections.unmodifiableList](/doc/%EA%B8%B0%EC%88%A0/%EC%9E%90%EB%B0%94/%EC%BB%AC%EB%A0%89%EC%85%98%20%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC/Collections.unmodifiableList)()등 제공. - Python:
[tuple](/doc/%EA%B8%B0%EC%88%A0/%ED%8C%8C%EC%9D%B4%EC%8D%AC/%EC%9E%90%EB%A3%8C%ED%98%95/tuple),[frozenset](/doc/%EA%B8%B0%EC%88%A0/%ED%8C%8C%EC%9D%B4%EC%8D%AC/%EC%9E%90%EB%A3%8C%ED%98%95/frozenset),str은 불변. 사용자 정의 클래스는[__slots__](/doc/%EA%B8%B0%EC%88%A0/%ED%8C%8C%EC%9D%B4%EC%8D%AC/%ED%81%B4%EB%9E%98%EC%8A%A4%20%EC%B5%9C%EC%A0%81%ED%99%94/__slots__)와 프로퍼티로 제어 가능. - C#:
[readonly](/doc/%EA%B8%B0%EC%88%A0/C%23/%EB%B6%88%EB%B3%80%EC%84%B1/readonly),record타입(특히record struct)을 통해 불변성 지원. - Kotlin:
[val](/doc/%EA%B8%B0%EC%88%A0/%EC%BD%94%ED%8B%80%EB%A6%B0/%EB%B3%80%EC%88%98%20%EC%84%A0%EC%96%B8/val)선언,[data class](/doc/%EA%B8%B0%EC%88%A0/%EC%BD%94%ED%8B%80%EB%A6%B0/%ED%81%B4%EB%9E%98%EC%8A%A4%20%EC%84%A4%EA%B3%84/data%20class)와 함께 불변성 강조.
참고 자료 및 관련 문서
- Oracle Java Documentation - Immutable Objects
- Joshua Bloch, 『Effective Java』, Item 17: "Minimize mutability"
- MDN Web Docs - Immutable data structures
- 함수형 프로그래밍, 불변성(Immutability), 스레드 안전성(Thread Safety), final 키워드
Immutable 객체는 현대 소프트웨어 개발에서 안정성과 유지보수성을 높이는 핵심 개념입니다. 특히 대규모 시스템이나 동시성 환경에서는 반드시 고려해야 할 설계 원칙 중 하나입니다. 객체의 상태를 변경하지 않고 새로운 객체를 생성함으로써, 예기치 않은 부작용을 방지하고 코드의 명확성을 높일 수 있습니다.
이 문서는 AI 모델(qwen-3-235b-a22b-instruct-2507)에 의해 생성된 콘텐츠입니다.
주의사항: AI가 생성한 내용은 부정확하거나 편향된 정보를 포함할 수 있습니다. 중요한 결정을 내리기 전에 반드시 신뢰할 수 있는 출처를 통해 정보를 확인하시기 바랍니다.